#ifndef __V2BUS_H__
#define __V2BUS_H__
#include <string>
#include <map>
#include <vector>

using namespace std;

namespace BUS
{
#define DEFAULT_MAX_BUS_ID  65536           //default value of maximum modules in BUS
#define DEFAULT_USR_BUS_ID  1024            //default start ID of user modules, less than which are system module IDs
#define DEFAULT_BUFFER_SZIE 4096            //default budder size for BUS messages queue,unit: KB 


    // ============================================================================
    // struct MSG: header of BUS message
    //   Each BUS message at least contain start with this MSG header, and followed
    //   by the message body with the length of bodyLen.
    // ============================================================================
    typedef struct MSG
    {
        int     srcId;                      //sender ID
        int     destId;                     //receiver ID
        int     sequenceNo;                 //sequence number
        int     ackNo;                      //message ACKnowledge sequence number, 0 means no need ACK
        int     msgId;                      //message ID
        int     msgType;                    //message type
        int     param1;                     //message parameter 1
        int     param2;                     //message parameter 2
        int     dataLen;                    //length of message body
    } _bus_msg;


    // ============================================================================
    // class API: interface of BUS module
    //   Each BUS module should interit from this API. 
    // ============================================================================
    class API
    {
        void    execute(MSG& msg);                  //called when a message arrived
    };


    // ============================================================================
    // class MOD: container of BUS module pointers
    //   . 
    // ============================================================================
    class MOD
    {
    public:
        MOD();
        ~MOD();

        int     hook(char* modName, API* apiAddr);  //register a module to BUS
        void    unhook(API* apiAddr);               //remove a module from BUS
        int     find(char* modName);                //get the index of a registered module

    private:
        map<string, int>    _modIndex;              //module name to api pointer
        vector<API*>        _apiList;               //list of all module APIs
        vector<int>         _recycle;               //list of the deleted index which could be reused
    };


    // ============================================================================
    // class PIPE: message pipe (FIFO) of BUS
    //   . 
    // ============================================================================
    class PIPE
    {
    public:
        PIPE();
        ~PIPE();

    private:
        char*   _bufferAddr;                    //base address of the message buffer
        int     _bufferSize;                    //memory size of the message buffer
        
        char*   _msgHead;                       //head address of the message queue
        char*   _msgTail;                       //tail address of the message queue
        int     _msgCount;                      //total number of messages
        int     _msgLength;                     //total length of all messages
        int     _msgSpace;                      //available space for the message

    public:
        bool    init(int bufferSize);           //initialize the PIPE with specify size
        void    destroy();                      //destroy the PIPE and release the memory
        bool    empty();                        //check PIPE is empty or not
        int     count();                        //return the message number in PIPE
        bool    send(MSG& msg, void* data);     //send a message to PIPE
        MSG*    first();                        //get the pointer of first message
        bool    remove(MSG* msg);               //remove the first message
    };

    extern MOD  __busModule;                    //global instance of BUS modules
    extern PIPE __busPipe;                      //global instance of BUS pipe

    // ============================================================================
    // BUS::func() member functions under BUS namespace
    //   
    // ============================================================================
    bool init();                                //initialize BUS
    bool send(MSG& msg, void* data);            //send a message to PIPE
    bool sendf(MSG& msg, void* data, ...);      //send a message to PIPE
    inline int  hook(char* modName, API* apiAddr){ return __busModule.hook(modName, apiAddr); }
    inline void unhook(API* apiAddr)            { return __busModule.unhook(apiAddr); }
    inline int  find(char* modName)             { return __busModule.find(modName); }
    inline bool empty()                         { return __busPipe.empty();         }
    inline MSG* first()                         { return __busPipe.first();         }
    inline bool remove(MSG* msg)                { return __busPipe.remove(msg);     }
    inline int  count()                         { return __busPipe.count();         }
}

#endif